using System;
using System.Globalization;
using System.Reflection;
using System.Reflection.Emit;
using RaisingStudio.SmallBasicCompiler.Completion;
using RaisingStudio.SmallBasicCompiler.Expressions;
using RaisingStudio.SmallProgram.Library;

namespace RaisingStudio.SmallBasicCompiler.Statements
{
    public class AssignmentStatement : Statement
    {
        public Expression LeftValue;
        public Expression RightValue;
        public TokenInfo EqualsToken;
        public override void AddSymbols(SymbolTable symbolTable)
        {
            if (this.LeftValue != null)
            {
                this.LeftValue.AddSymbols(symbolTable);
            }
            if (this.RightValue != null)
            {
                this.RightValue.AddSymbols(symbolTable);
            }
            IdentifierExpression identifierExpression = this.LeftValue as IdentifierExpression;
            ArrayExpression arrayExpression = this.LeftValue as ArrayExpression;
            if (identifierExpression != null)
            {
                identifierExpression.AddSymbolInitialization(symbolTable);
                return;
            }
            if (arrayExpression != null)
            {
                arrayExpression.AddSymbolInitialization(symbolTable);
            }
        }
        public override void EmitIL(CodeGenScope scope)
        {
            IdentifierExpression identifierExpression = this.LeftValue as IdentifierExpression;
            PropertyExpression propertyExpression = this.LeftValue as PropertyExpression;
            ArrayExpression arrayExpression = this.LeftValue as ArrayExpression;
            if (identifierExpression != null)
            {
                this.RightValue.EmitIL(scope);
                FieldInfo field = scope.Fields[identifierExpression.Identifier.NormalizedText];
                scope.ILGenerator.Emit(OpCodes.Stsfld, field);
                return;
            }
            if (arrayExpression != null)
            {
                this.RightValue.EmitIL(scope);
                arrayExpression.EmitILForSetter(scope);
                return;
            }
            if (propertyExpression != null)
            {
                TypeInfo typeInfo = scope.TypeInfoBag.Types[propertyExpression.TypeName.NormalizedText];
                EventInfo eventInfo;
                if (typeInfo.Events.TryGetValue(propertyExpression.PropertyName.NormalizedText, out eventInfo))
                {
                    IdentifierExpression identifierExpression2 = this.RightValue as IdentifierExpression;
                    TokenInfo tokenInfo = scope.SymbolTable.Subroutines[identifierExpression2.Identifier.NormalizedText];
                    MethodBuilder meth = scope.MethodBuilders[tokenInfo.NormalizedText];
                    scope.ILGenerator.Emit(OpCodes.Ldnull);
                    scope.ILGenerator.Emit(OpCodes.Ldftn, meth);
                    scope.ILGenerator.Emit(OpCodes.Newobj, typeof(SmallProgramCallback).GetConstructors()[0]);
                    scope.ILGenerator.EmitCall(OpCodes.Call, eventInfo.GetAddMethod(), null);
                    return;
                }
                PropertyInfo propertyInfo = typeInfo.Properties[propertyExpression.PropertyName.NormalizedText];
                MethodInfo setMethod = propertyInfo.GetSetMethod();
                this.RightValue.EmitIL(scope);
                scope.ILGenerator.EmitCall(OpCodes.Call, setMethod, null);
            }
        }
        public override void PopulateCompletionItems(CompletionBag completionBag, int line, int column, bool globalScope)
        {
            if (this.EqualsToken.Token == Token.Illegal || column <= this.EqualsToken.Column)
            {
                CompletionHelper.FillAllGlobalItems(completionBag, globalScope);
                return;
            }
            CompletionHelper.FillExpressionItems(completionBag);
        }
        public override string ToString()
        {
            return string.Format(CultureInfo.CurrentUICulture, "{0} {1} {2}\r\n", new object[]
			{
				this.LeftValue, 
				this.EqualsToken.Text, 
				this.RightValue
			});
        }
    }
}
